--[[
 -- *名称:FourTakeSingleTypeAnalyzer
 -- *描述:四带一
 -- *版权:Copyright © 2016-2018 深圳市三只小熊科技有限公司 版权所有
 -- *作者:Administrator
 -- *创建日期:2017-11-10
 -- *修改日期:2017-11-10
 ]]
local DdzSuitAnalyzer = require(basePath.."suit/ddzsuitanalyzer");
local FourTakeSingleTypeAnalyzer = pokercore.class(DdzSuitAnalyzer,false);
local SingleAnalyzer = require(basePath .. "suit/single/singletypeanalyzer") ;
local BombTypeAnalyzer =  require(basePath.."suit/bomb/bombtypeanalyzer");
local Cards = require(basePath .. "domain/cards");
local singleTypeAnalyzer = pokercore.new(SingleAnalyzer);
FourTakeSingleTypeAnalyzer.TUPLE_SIZE = 6 ;
local TUPLE_SIZE = 6 ;

function FourTakeSingleTypeAnalyzer:getSuitType()
	return DdzCardTypes.FOUR_TAKE_SINGLE;
end

--@Override
function FourTakeSingleTypeAnalyzer:doCheckRule(cards,term,result)
	if (result:getCardNum() == TUPLE_SIZE) then -- // 六的倍数，考虑 444435
		if (result:isAllCardLazi()) then -- // 全是癞子
			--print("FourTakeSingleTypeAnalyzer:doCheckRule 1");
			return false;
		else 
			local allValues = result:getNoneLaziValueCounter():getAllValues(); --// 非癞子的点数
			if (#allValues > 3) then-- // 四带二牌型最大只有3种点数
				--print("FourTakeSingleTypeAnalyzer:doCheckRule 2");
				return false;
			else 
				local laiziCardNum = result:getLaziCardNum();
				for _,number in ipairs(allValues) do
					local valueNum = result:getNoneLaziValueCounter():getValueCount(number);
					if (valueNum + laiziCardNum >= 4) then -- // 验证能够组成四张 23344*
						return true;
					end
				end
				--print("FourTakeSingleTypeAnalyzer:doCheckRule 3");
				return false;
			end
		end
	else 
		--print("FourTakeSingleTypeAnalyzer:doCheckRule 4");
		return false;
	end
end

--@Override
function FourTakeSingleTypeAnalyzer:doAnalysizeLaizi(cards,term,onlyMaxValue)
	local cardsResult = {};
	local result = cards:getResult();
	local laiziCardList = cards:subList(result:getCardNum() - result:getLaziCardNum()+1, result:getCardNum())
	local laiziCardNum = result:getLaziCardNum();
	local allValues = result:getNoneLaziValueCounter():getAllValues(); -- // 非癞子的点数
	if (laiziCardNum >= 4) then --此时最多可能只有4个癞子，可组成任意牌型
		for valueTemp = PokerGameConstant.NUMBER_2_VALUE, PokerGameConstant.NUMBER_3_VALUE, -1 do
			local valueTempNum = result:getNoneLaziValueCounter():getValueCount(valueTemp);
			local needLaiziNum = 4 - valueTempNum; --// 需要填补几个癞子
			for i = 1 , laiziCardNum do
				local ddzCard = laiziCardList[i];
				if (i <= needLaiziNum) then
					ddzCard:changeCard(valueTemp);
				else 
					ddzCard:changeCard(ddzCard:getNumber());
				end
			end
			local cardsCopy = cards:clone();
			self:analysize(cardsCopy, term);
			table.insert(cardsResult,cardsCopy:clone());
			if (onlyMaxValue) then
				break; -- // 取完最大一组就跳出
			end
		 end
	else
		for i = #allValues , 1, -1 do
			local valueTemp = allValues[i];
			local valueTempNum = result:getNoneLaziValueCounter():getValueCount(valueTemp);
			local needLaiziNum = 4 - valueTempNum; --// 需要填补几个癞子
			if (laiziCardNum >= needLaiziNum) then -- // 可能癞子不够
				for  j = 1, laiziCardNum do
					local ddzCard = laiziCardList[j];
					if (j <= needLaiziNum) then
						ddzCard:changeCard(valueTemp);
					else 
						ddzCard:changeCard(ddzCard:getNumber());
					end
				end
				local cardsCopy = cards:clone();
				self:analysize(cardsCopy, term);
				table.insert(cardsResult,cardsCopy:clone());
				if (onlyMaxValue) then
					break; --// 取完最大一组就跳出
				end
			end
		end
	end
	return cardsResult;
end

--提牌算法

	
--@Override
function FourTakeSingleTypeAnalyzer:containsPossibleCards(handCards,term) 
	return handCards:getResult():getCardNum() >= TUPLE_SIZE;
end

--/** 最多使用癞子的数量 */
local MAX_USE_LAIZI_CARD_NUM = 6;

-- 防重复判定的比例值 参照 int key = count_3_value * TUPLE_WEIGHT + count_1_value_a + count_1_value_b; */
local TUPLE_WEIGHT = 1000000;

--/** 癞子权重，区分癞子变成的5 和 原本就是5 */
local LAIZI_WEIGHT = 1000;
	
--@Override
function FourTakeSingleTypeAnalyzer:doListPossibleCards(handCards,term)
	local cardsResult = {};
	--// 非癞子部分
	local result = handCards:getResult();
	local noneLaiziCardList = handCards:subList(1, result:getNoneCardNum());
	local noneLaiziCards = DdzTypeUtil.createCardsCopy(noneLaiziCardList);
	noneLaiziCards:setResult(handCards:getResult():clone());
	local noneLaiziCardsResult = noneLaiziCards:getResult();
	noneLaiziCardsResult:collectNumber(noneLaiziCards, term);
	--// 癞子部分
	local laiziCardList = handCards:subList(result:getNoneCardNum()+1, result:getCardNum());
	local laiziCards = DdzTypeUtil.createCardsCopy(laiziCardList);
	laiziCards:setResult(handCards:getResult():clone());
	local laiziCardsResult =  laiziCards:getResult();
	laiziCardsResult:collectNumber(laiziCards, term);
	
	local maxLoseValue = 0; -- // 寻找最大遗失的牌 让***5可以出现，但是仅一次
	for  valueTemp = PokerGameConstant.NUMBER_2_VALUE -- // 从小开始
			,PokerGameConstant.NUMBER_3_VALUE, -1 do
		if (result:getNoneLaziValueCounter():getValueCount(valueTemp) == 0) then
			maxLoseValue = valueTemp;
			break;
		end
	end
	local laiziCardNum = result:getLaziCardNum();
	local maxUseLaiziCardNum = MAX_USE_LAIZI_CARD_NUM < laiziCardNum and MAX_USE_LAIZI_CARD_NUM or laiziCardNum;
	local exsitKeys = {} ;-- // 记录已经组成三带一的value
	for useLaiziCardNum = 0,  maxUseLaiziCardNum do
		if (useLaiziCardNum < MAX_USE_LAIZI_CARD_NUM) then --// 用了 0.1.2.3 个癞子
			for valueTemp = PokerGameConstant.NUMBER_3_VALUE --// 从小开始
					, PokerGameConstant.NUMBER_2_VALUE do
				local modelCardsCopy = noneLaiziCards:clone(); --// 常规牌副本
				local modelResultCopy = modelCardsCopy:getResult();
				local useLaiziCardList = DdzTypeUtil.cloneSublistedCards(laiziCards, 1, useLaiziCardNum); --// 补癞子
				local valueTempNum = modelResultCopy:getNoneLaziValueCounter():getValueCount(valueTemp);
				local needLaiziCardNum = BombTypeAnalyzer.TUPLE_SIZE - valueTempNum;
				needLaiziCardNum = needLaiziCardNum > 0 and needLaiziCardNum or 0;
				if (needLaiziCardNum == 0) then 
					--dump(modelCardsCopy,"modelCardsCopy");
					local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, BombTypeAnalyzer.TUPLE_SIZE);
					local tupleCards = pokercore.new(Cards,removedCardList);
					local remainCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardList);
					--dump(remainCards,"remainCards");
					local takenCardsList = self:repeatSelectSingleCards(remainCards, 2, term);
					--dump(takenCardsList,"takenCardsList");
					--dump(tupleCards,"tupleCards");
					for _,takenCards in ipairs(takenCardsList) do
						local resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
						local key = valueTemp * TUPLE_WEIGHT;
						for _,card in ipairs(takenCards.cardList) do
							key = key + card:getValue();
							if card:isLazi() then -- // 癞子权重，区分癞子变成的5 和 原本就是5
								key = key + card:getValue() * LAIZI_WEIGHT;
							end
						end
						if (not exsitKeys[key] and self:match(resultCards, term)) then
							exsitKeys[key] = true;
							--// 保证排序
							resultCards:getResult():setSortFirstValue(valueTemp);
							self:analysize(resultCards, term);
							table.insert(cardsResult,resultCards);
						end
					end
				else -- // 需要癞子来拼凑
					if (needLaiziCardNum == BombTypeAnalyzer.TUPLE_SIZE 
							and valueTemp ~= maxLoseValue) then
						--// 这里是对癞子做tuple的去重
						--// 否则会出现 ****带7799 既能是 3333带7799 也能是 4444带7799  5555带7799 
						--continue;
					
					elseif (useLaiziCardNum >= needLaiziCardNum) then -- // 癞子足够拼凑
						local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, valueTempNum);
						for i = 1, needLaiziCardNum do
							local laiziCard = table.remove(useLaiziCardList,1);
							laiziCard:changeCard(valueTemp);
							table.insert(removedCardList,laiziCard);
						end
						for _,laiziCard in ipairs(useLaiziCardList) do
							laiziCard:changeCard(laiziCard:getValue());
						end
						local tupleCards = pokercore.new(Cards,removedCardList);
						local remainCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardList);
						local takenCardsList = self:repeatSelectSingleCards(remainCards, 2, term);
						for _, takenCards in ipairs(takenCardsList) do
							local resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
							local key = valueTemp * TUPLE_WEIGHT;
							for _,card in ipairs(takenCards.cardList) do
								key = key + card:getValue();
								if card:isLazi() then -- // 癞子权重，区分癞子变成的5 和 原本就是5
									key = key + card:getValue() * LAIZI_WEIGHT;
								end
							end
							if not exsitKeys[key] and self:match(resultCards, term) then
								exsitKeys[key] = true;
								--// 保证排序
								resultCards:getResult():setSortFirstValue(valueTemp);
								self:analysize(resultCards, term);
								table.insert(cardsResult,resultCards);
							end
						end
					end
				end
			end
		else -- // 用了 5个癞子
			for valueTemp = PokerGameConstant.NUMBER_3_VALUE --// 从小开始
					, PokerGameConstant.NUMBER_2_VALUE do
				local modelCardsCopy = laiziCards:clone();  --// 常规牌补上癞子
				local modelResultCopy =  modelCardsCopy:getResult();
				if (modelResultCopy:getAllValueCounter():getValueCount(valueTemp) >= BombTypeAnalyzer.TUPLE_SIZE) then
					local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, BombTypeAnalyzer.TUPLE_SIZE);
					local tupleCards = pokercore.new(Cards,removedCardList);
					local takenCardsList = self:repeatSelectSingleCards(modelCardsCopy, 2, term);
					for _,takenCards in ipairs(takenCardsList) do
						local resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
						for _,card in ipairs(resultCards) do
							if card:hasNotChanged() then -- // 有的经过处理已经被赋值了不能再改变
								card:changeCard(card:getValue());
							end
						end
						if (self:match(resultCards, term)) then
							--// 保证排序
							resultCards:getResult():setSortFirstValue(valueTemp);
							self:analysize(resultCards, term);
							table.insert(cardsResult,resultCards);
						end
					end
				end
			end
		end
	end
	return cardsResult;
end

--[[
/**
 * 在固定牌组中寻找repeat张单牌 <br>
 * 比如在 5。5。6。7 中寻找两张单牌 5.5 5.6 5.7 6.7   注意这里已经去重了 6.7 和 7.6 不会同时出现 
 * 
 * @param cards
 * @param repeat
 * @param term
 * @param onlyMaxValue
 * @return
 */]]
function FourTakeSingleTypeAnalyzer:repeatSelectSingleCards( cards,  repeatSize,  term) 
	local modelCards = DdzTypeUtil.cloneCardsAndAddCardList(cards, nil); --// 常规牌补上癞子
	local modelResult = modelCards:getResult();
	modelResult:collectNumber(modelCards, term);
	if (modelResult:getCardNum() < repeatSize) then --// 数量不足
		print("数量不足");
		return {};
	end
	----dump(modelCards,"##############modelCards--->");
	local resultCardsList = singleTypeAnalyzer:listPossibleCards(modelCards, term); --// 记录最终结果
	----dump(resultCardsList,"##################resultCardsList--->");
	if (#resultCardsList ~= 0) then
		for i = 1,repeatSize-1 do -- // 上面已经获取了一次了
			local exsitKeys = {} -- // 每一步都去重
			local currentCardsList = pokercore.clone(resultCardsList);
			resultCardsList = {}; --// 清空上一步的结果
			for _,preCards in ipairs(currentCardsList) do
				local remainCards = DdzTypeUtil.cloneCardsAndRemoveCards(modelCards, preCards);
				local nextCardsList = singleTypeAnalyzer:listPossibleCards(remainCards, term);
				for _,nextCards in ipairs(nextCardsList) do
					local combinedCards = DdzTypeUtil.cloneCardsAndAddCards(preCards, nextCards);
					local key = 0;
					for _,card in ipairs(combinedCards) do
						key = key + card.getValue();
						if card:isLazi() then -- // 癞子权重，区分癞子变成的5 和 原本就是5
							key = key + LAIZI_WEIGHT;
						end
					end
					if (not exsitKeys[key]) then
						exsitKeys[key] = true;
						table.insert(resultCardsList,combinedCards);
					end
				end
			end
		end
	end
	return resultCardsList;
end

return FourTakeSingleTypeAnalyzer;

